import os
from utils.persist import save_to_pickle, load_from_pickle
from utils.namespace import Namespace

from stacking.action import Action
from stacking.solution.player import Player


class Solution(object):
    """Solution class for the Stacking Problem. A solution is merely a sequence of crane actions,
    i.e. picking up one or more items from one place or putting down one or more items."""
    pickle_protocol = 2
    
    def __init__(self, instance, **meta):
        self.actions = list()
        self.instance = instance
        self.meta = Namespace(meta)
        
    def rpickup(self, *args, **kwargs):
        """Create a release action (i.e. a "pick up" from a warehouse entrance) and append it to 
        the solution. The new action is also returned."""
        action = Action.rpickup(len(self.actions), *args, **kwargs)
        self.actions.append(action)
        return action
        
    def pickup(self, *args, **kwargs):
        """Create a "pick up" action and append it to the solution. The new action is also 
        returned."""
        action = Action.pickup(len(self.actions), *args, **kwargs)
        self.actions.append(action)
        return action
        
    def putdown(self, *args, **kwargs):
        """Create a "put down" action and append it to the solution. The new action is also 
        returned."""
        action = Action.putdown(len(self.actions), *args, **kwargs)
        self.actions.append(action)
        return action
        
    def dputdown(self, *args, **kwargs):
        """Create a delivery action (i.e. a "put down" onto a warehouse exit) and append it to the 
        solution. The new action is also returned."""
        action = Action.dputdown(len(self.actions), *args, **kwargs)
        self.actions.append(action)
        return action
        
    def player(self):
        return Player(self)
        
    @classmethod
    def load(cls, filepath):
        return load_from_pickle(filepath, cls.pickle_protocol)
        
    def save(self, filepath=None):
        if filepath is None:
            try:
                filepath = os.path.join(self.meta.directory, self.meta.filename)
            except KeyError:
                raise Exception("output file path required")
        filepath = os.path.abspath(filepath)
        dir, file = os.path.split(filepath)
        self.meta.filename = file
        self.meta.directory = dir
        save_to_pickle(self, filepath, self.pickle_protocol)
        
        
